package de.playmee.geo;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.Paint.Style;
import android.view.MotionEvent;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

public class BubbleOverlay extends Overlay {
	
	public static String TAG = "BubbleOverlay";
	
	// paint of text box and label
	private static Paint innerPaint = new Paint();
	private static Paint borderPaint = new Paint();
	private static Paint textPaint = new Paint();
	
	static {
		innerPaint.setARGB(75, 75, 75, 75);
		innerPaint.setAntiAlias(true);
		innerPaint.setStyle(Paint.Style.FILL);
		
		borderPaint.setARGB(255, 75, 75, 75);
		borderPaint.setAntiAlias(true);
		borderPaint.setStyle(Style.STROKE);
		borderPaint.setStrokeWidth(2);
		
		textPaint.setARGB(255, 255, 255, 255);
		textPaint.setAntiAlias(true);
	}
	
	// label box and content settings
	private static int labelBoxWidth = 125, labelBoxHeight = 25;
	private static int labelOffsetX = 10, labelOffsetY = 15;
	
	
	// bubble image and last text box
	private Bitmap bubble;
	private RectF labelBox;
	
	// localization data and label to draw 
	private String label;
	private GeoPoint position;
	
	protected boolean drawLabel = false;
	private boolean touched = false;
	
	public BubbleOverlay(Bitmap bubble) {
		init(bubble);
	}
	
	public BubbleOverlay(Bitmap bubble, String label, GeoPoint position) {
		this.label = label;
		this.position = position;
		init(bubble);
	}
	
	private void init(Bitmap bubble) {
		this.bubble = bubble;
		labelBox = new RectF(0, 0, labelBoxWidth, labelBoxHeight);
	}
	
	public void draw(String label, GeoPoint position, Canvas canvas, MapView mapView, boolean shadow) {
		this.label = label;
		this.position = position;
		draw(canvas, mapView, shadow);
	}
	
	public void draw(Canvas canvas, MapView mapView, boolean shadow) {
		super.draw(canvas, mapView, shadow);

		// compute screen coordinates
		Point p = new Point();
		mapView.getProjection().toPixels(position, p);
		
		// draw bubble image
		canvas.drawBitmap(bubble, p.x - bubble.getWidth()/2, p.y - bubble.getHeight(), null);
		
		// label:
		if (drawLabel()) {
			// compute new position of the label box
			float offsetX = p.x - labelBoxWidth/2;
			float offsetY = p.y - labelBoxHeight - bubble.getHeight();
			
	    	//  update labelBox location
			labelBox.offset(offsetX - labelBox.left, offsetY - labelBox.top);
			
			//  draw inner
			canvas.drawRoundRect(labelBox, 5, 5, innerPaint);
			//  draw border
			canvas.drawRoundRect(labelBox, 5, 5, borderPaint);
				
			//  draw label
			canvas.drawText(label, offsetX + labelOffsetX, offsetY + labelOffsetY, textPaint);
		}
	}
	
	public boolean onTouchEvent(MotionEvent event, MapView mapView) {
		boolean res = false;
		// get GeoPoint by screen coordinates
		GeoPoint hitPoint = mapView.getProjection().fromPixels((int)event.getX(), (int)event.getY());
		switch(event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			// check if bubble was touched
			touched = isHitBubble(hitPoint, mapView);
			break;
		case MotionEvent.ACTION_UP:
			// toggle textbox
			if (touched && isHitBubble(hitPoint, mapView)) {
				drawLabel = !drawLabel;
				res = true;
			}
			touched = false;
			break;
		}
		return res;
	}
	
	/**
	 * computes whether the given hit point intersects bubbles bounding box
	 * @param hit
	 * @param mapView
	 * @return true, if hit intersects bubble
	 */
	public boolean isHitBubble(GeoPoint hit, MapView mapView) {
		// get bounding box and 
		RectF bbox = new RectF();
		Point screenCoords = new Point();
		Projection projection = mapView.getProjection();
		projection.toPixels(position, screenCoords);
		bbox.set(-bubble.getWidth()/2, -bubble.getHeight(), bubble.getWidth(), 0);
		bbox.offset(screenCoords.x, screenCoords.y);
		
		projection.toPixels(hit, screenCoords);
		
		// check if this box contains hit points screen coordinates
		return bbox.contains(screenCoords.x, screenCoords.y);
	}
	
	/**
	 * computes if the given hit point intersects the text box
	 * @param hit
	 * @param mapView
	 * @return true, if hit intersects the text box
	 */
	public boolean labelBoxTouched(GeoPoint hit, MapView mapView) {
		Point screenCoords = new Point();		
		(mapView.getProjection()).toPixels(hit, screenCoords);
		
		return drawLabel() && labelBox.contains(screenCoords.x, screenCoords.y);
	}
	
	
	// getters and setters 
	public boolean drawLabel() {
		return drawLabel && !label.isEmpty();
	}
	
	public boolean getDrawLabel() {
		return drawLabel;
	}
	
	public void setDrawLabel(boolean drawLabel) {
		this.drawLabel = drawLabel;
	}
	
	public String getLabel() {
		return label;
	}
	
	public void setLabel(String label) {
		this.label = label;
	}

	public GeoPoint getPosition() {
		return position;
	}

	public void setPosition(GeoPoint position) {
		this.position = position;
	}
}
